﻿using FDSimpleModelGenerator.Common;
using FDSimpleModelGenerator.Common.Enums;
using FDSimpleModelGenerator.Entities;
using FDSimpleModelGenerator.Entities.Enums;
using FDSimpleModelGenerator.IServices;
using MySql.Data.MySqlClient;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace FDSimpleModelGenerator.Services.MySql
{
    /// <summary>
    /// 生成MySql模型
    /// </summary>
    public class GenerateModelMySqlService : IGenerateModelService
    {
        private readonly IExceptionThrowFactory _exceptionThrowFactory;
        private readonly IDbConfigResolver _configResolver;
        private readonly IDbAccessor _dbAccessor;
        private readonly IModelGenerateEngine _modelGenerateEngine;

        public GenerateModelMySqlService(IExceptionThrowFactory exceptionThrowFactory, IDbAccessor dbAccessor,
            IModelGenerateEngine modelGenerateEngine, IEnumerable<IDbConfigResolver> dbConfigResolvers)
        {
            _modelGenerateEngine = modelGenerateEngine;
            _dbAccessor = dbAccessor;
            _exceptionThrowFactory = exceptionThrowFactory;
            _configResolver = dbConfigResolvers.First(r => r.DbType == DbType);
        }

        public DbType DbType => DbType.MySql;

        /// <summary>
        /// 生成模型
        /// </summary>
        /// <param name="dbConfig"></param>
        /// <param name="tableName"></param>
        /// <param name="templateContent"></param>
        /// <param name="namespaceName">命名空间</param>
        /// <param name="propertyFirstCharLower"></param>
        /// <param name="languageDataType">语言数据类型</param>
        /// <returns></returns>
        public string Generate(DbConfig dbConfig, string tableName, string templateContent,
            string namespaceName, LanguageDataType languageDataType, bool propertyFirstCharLower)
        {
            return GenerateAsync(dbConfig, tableName, templateContent, namespaceName, languageDataType, propertyFirstCharLower).Result;
        }

        /// <summary>
        /// 生成模型
        /// </summary>
        /// <param name="dbConfig"></param>
        /// <param name="tableName"></param>
        /// <param name="templateContent"></param>
        /// <param name="namespaceName">命名空间</param>
        /// <param name="propertyFirstCharLower"></param>
        /// <param name="languageDataType"></param>
        /// <returns></returns>
        public async Task<string> GenerateAsync(DbConfig dbConfig, string tableName, string templateContent, string namespaceName, LanguageDataType languageDataType, bool propertyFirstCharLower)
        {
            var connString = await _configResolver.GetConnectionStringAsync(dbConfig);
            await _dbAccessor.InitAsync(() => new MySqlConnection(connString));
            var sql =
                @"SELECT COLUMN_NAME `name`,DATA_TYPE ColumnType,INSTR(column_type,'unsigned')>0 `Unsigned`,column_comment Description,character_maximum_length Length,numeric_precision `precision`, 
	CASE WHEN column_key='PRI' THEN 1 ELSE 0 END `Key` FROM information_schema.COLUMNS WHERE table_schema=@dbName  
	AND table_name=@tableName;";

            var sqlTable = @"select table_name Name,table_comment Value from information_schema.tables where table_schema=@dbName and table_name=@tableName";
            var tableInfo = _dbAccessor.Get<NameValue<string>>(sqlTable, new { tableName, dbName = dbConfig.Database });
            var columns = _dbAccessor.GetList<TableColumn>(sql, new { tableName, dbName = dbConfig.Database });

            var tableParam = new TableInfo
            {
                Description = tableInfo.Value,
                Name = tableInfo.Name,
                TableColumns = columns
            };
            return await _modelGenerateEngine.GenerateAsync(tableParam, templateContent, namespaceName, languageDataType, propertyFirstCharLower);
        }

    }
}
